import axios from "axios";
import { message } from "antd";

// interface ResponseData<T> {
//   code: number;
//   data: T;
//   message: string;
// }

// 创建一个新的axios，就是返回值request
// request的用法和axios用法基本一致
const request = axios.create({
  // 公共配置，将来发送请求会自动添加
  // 发送请求的前缀：将来所有通过request发送的请求，会在请求地址前面自动添加baseURL
  // react脚手架会根据开发/生产自动加载.env.xxx的环境变量
  // 通过 process.env.xxx 读取加载的环境变量的值
  // 开发模式下：process.env.REACT_APP_API --> /dev-api
  baseURL: process.env.REACT_APP_API, // 请求地址：baseURL + url
  timeout: 10000, // 请求超时时间：一旦请求超过10s还未完成，就会自动中断请求
  // headers: {},
});

/*
  封装axios的目的：为了复用代码
    1. 发送请求请求地址都有公共前缀 --> baseURL
    2. 发送请求存在公共的请求参数 --> 请求拦截器的回调函数中
      token 请求头参数

      create方法只会执行一次。
      请求拦截器每次发送请求都会触发。

      如果参数是可变的，只能在请求拦截器
      如果参数是固定的，可以在create中配置
    3. 得到响应，成功得到响应的数据，失败得到失败原因

  使用request发送请求，触发流程：
    1. 触发请求拦截器设置回调函数
      做什么？ 设置公共请求参数
    2. 发送请求
    3. 响应回来了，触发响应拦截器设置回调函数
      做什么？ 
        请求成功并且功能成功得到成功的数据
        请求失败或功能失败，得到失败原因并且要触发失败流程

        成功的回调（响应状态码status 2xx）
          得到最终需要使用数据
            axios请求返回值：
              {
                config: xxx, // 请求配置对象
                headers: xxx, // 响应头
                request: xxx, // 发送请求的xhr对象
                status: xxx, // 响应状态码（只能代表请求成功，不能代表功能成功）
                data: { // 响应体数据（服务器响应的数据）
                  code: 200, （代表功能成功）
                  success: true,
                  message: null, // 失败原因
                  data: xxx, // 具体的数据（我们最终希望得到的数据）
                } 
              }

        失败的回调（响应状态码status 不是2xx, 比如：4xx 5xx）
          得到失败的原因
    4. 触发调用请求函数后面的代码 （async await）
*/

// 请求拦截器函数：发送请求之前触发的函数
request.interceptors.request.use((config) => {
  // config就是请求的配置对象（url,params,data）
  const token = localStorage.getItem("token");
  // 携带token
  if (token) {
    (config.headers as any).token = token; // 用户的唯一标识，可以简单看做用户id（实际不是）
  }
  // config.params.xxx = xxx // 添加公共query参数
  // config.data.xxx = xxx // 添加公共body参数
  return config;
});

// 响应拦截器函数：得到响应之后触发的函数
request.interceptors.response.use(
  (response) => {
    // 请求成功
    if (response.data.code === 200) {
      // 说明功能成功，返回成功的数据
      return response.data.data; // 我们最终希望得到的数据
    } else {
      // 说明功能失败，没有数据，返回失败的原因
      message.error(response.data.message);
      return Promise.reject(response.data.message); // 外面触发失败的流程
    }
  },
  (error) => {
    // 请求失败
    message.error(error);
    return Promise.reject(error);
  }
);

export default request;
